package com.vmj.instructions.references;

import com.vmj.common.BytesReader;
import com.vmj.heap.ArrayObject;
import com.vmj.heap.VMClass;
import com.vmj.heap.ClassRef;
import com.vmj.heap.RuntimeConstantPool;
import com.vmj.heap.VMObject;
import com.vmj.instructions.base.Instruction;
import com.vmj.rtda.Frame;
import com.vmj.rtda.OperandStack;

/**
 * Created by yangshoujun on 2017/9/9 下午4:50.
 */
public class MultiANewArray implements Instruction {

    short index;
    byte demensions;

    public void fetchOperands(BytesReader reader) {
        index = reader.readShort();
        demensions = reader.readByte();
    }

    public void execute(Frame frame) {
        RuntimeConstantPool cp = frame.getMethod().getClazz().getRuntimeConstantPool();
        ClassRef classRef = (ClassRef) cp.getConstant(index).getValue();
        VMClass arrClass = classRef.resolvedClass();
        OperandStack stack = frame.getOperandStack();
        int[] counts = popAndCheckCounts(stack, demensions);
        VMObject arr = ArrayObject.newMultiDemensionalArray(counts, arrClass);
        stack.pushRef(arr);
    }

    private int[] popAndCheckCounts(OperandStack stack, int demensions) {
        int[] counts = new int[demensions];
        for(int i = counts.length - 1; i >= 0;i--) {
            counts[i] = stack.popInt();
            if(counts[i] < 0) {
                throw new RuntimeException("java.lang.NagativeArraySizeException");
            }
        }
        return counts;
    }



    public short getIndex() {
        return index;
    }

    public byte getDemensions() {
        return demensions;
    }

    public void setIndex(short index) {
        this.index = index;
    }

    public void setDemensions(byte demensions) {
        this.demensions = demensions;
    }
}
